<?php

namespace App\Services\Maze;


use App\Services\BaseServices;
use Illuminate\Support\Facades\Redis;

class MazeServices extends BaseServices
{
    protected $dirs = [
        [-1, 0],
        [0, -1],
        [1, 0],
        [0, 1]
    ];

    /**
     * @param  string  $fileName
     * @return \int[][]
     */
    public function readMaze(string $fileName)
    {
        $maze = [
            [0, 1, 0, 0, 0],
            [0, 0, 0, 1, 0],
            [0, 1, 0, 1, 0],
            [1, 1, 1, 0, 0],
            [0, 1, 0, 0, 1],
            [0, 1, 0, 0, 0]
        ];
        return $maze;
    }

    /**
     * @param  array  $maze
     * @param  array  $start
     * @param  array  $end
     * @return array
     */
    public function walk(array $maze, array $start, array $end)
    {
        $steps = [
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0]
        ];
        $lu = $start;
        Redis::lpush("maze",$lu);
        for($i=0;$i<Redis::llen('maze');$i++) {
            $cur = Redis::brpop("maze",10);
            if ($cur == $end) {
                break;
            }
            foreach ($this->dirs as $dir) {
                $next = $this->add($lu,$dir);
                $val = $this->at($lu,$maze);
                if ($val === false || $val == 1) {
                    continue;
                }
                $val2 = $this->at($lu,$steps);
                if ($val2 === false || $val2 != 0) {
                    continue;
                }
                if ($next == $start) {
                    continue;
                }
                $curSteps = $this->at($lu,$steps);
                $steps[$next[0]][$next[1]] = $curSteps + 1;
                Redis::lpush("maze",$next);
            }
        }
        return $steps;
    }

    /**
     * @param $start
     * @param $dir
     * @return array
     */
    public function add($lu,$dir)
    {
        return [$lu[0] + $dir[0],$lu[1] + $dir[1]];
    }

    /**
     * @param $start
     * @param $grid
     * @return false
     */
    public function at($lu,$grid)
    {
        if ($lu[0] < 0 || $lu[0] >= count($grid)) {
            return false;
        }
        if ($lu[1] < 0 || $lu[1] >= count($grid[$lu[0]])) {
            return false;
        }
        return $grid[$lu[0]][$lu[1]];
    }
}
